
import { UtilsHelper } from "utils/position/UtilsHelper";
import { StructureEntity } from "../StructureEntity";
import { PositionHelper } from "utils/position/PositionHelper";
import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { ActionArgHelper } from "GameLoop/Execution/ControlManager/Control/ActionManager/ActionArgHelper";
import { cache_return } from "utils/decorate/decorate";
 


export abstract class MineEntity<T extends IBaseMineMemory=IBaseMineMemory,V extends IRoomModuleInitializer=IRoomModuleInitializer>  extends StructureEntity<T,V> implements IMineInterface
{
     
   
    protected _pickupPos!:RoomPosition[];// 拾取的坐标
    protected _path!:RoomPosition[];    // 路径
    protected _source!:{id:Id<Source>,pos:RoomPosition} 
    get RoomType()
    {
        return Memory.rooms[this.roomName].config.type
    }
    protected initPath(nodememory:T)
    {

        if(!nodememory.pathkey|| !StationNetwork.getInstance.getPathCacheByKey(nodememory.pathkey))
        {
            const centerpos = this.lordRoom.getNodeMemory().center as [number,number];
            const startpos = PositionHelper.Create({x:centerpos[0],y:centerpos[1],roomName:this.lordRoom.name})
            const path = StationNetwork.getInstance.searchRoad(startpos,{pos:this.BasePosition,range:1},{});
            if(!path||path.path.length ==0 )
            {
                throw new Error(` 路径初始化失败: ${this.GUID()}`);
            }
            const cacheret = StationNetwork.getInstance.addRoadCache(path.path[0],path);
            nodememory.pathkey = cacheret.key
        }
        if( nodememory.pathkey)
        {
            const cacheret = StationNetwork.getInstance.getPathCacheByKey(nodememory.pathkey);
            if(cacheret)
            {
                this._path = UtilsHelper.deserializePathCache(cacheret.path);
            }
        }
    }
    public updateState(state:number)
    {
        this.getNodeMemory().state = state;
         
    }
    public testFindPath()
    {
        const centerpos = this.lordRoom.getNodeMemory().center as [number,number];
            const startpos = PositionHelper.Create({x:centerpos[0],y:centerpos[1],roomName:this.region})
        const path = StationNetwork.getInstance.searchRoad(startpos ,{pos:this.BasePosition,range:1},{});
        return path
    }
    public getSource(): Source 
    {
        return Game.getObjectById(this._source.id) as Source
        // return Game.getObjectById(this.getNodeMemory().source.id as Id<Source>) as Source
        // throw new Error("Method not implemented.");
    }

    public getContainer()
    {
        return Game.getObjectById(this.getNodeMemory().containerId as Id<StructureContainer> )
    }

    abstract getTransferObject():AnyStoreStructure |null;
     
    /**
     * 获取可拾取对象  默认为能量
     * @param resourceType 
     * @param amount 
     * @returns 
     */
    public getPickUpItem(resourceType:ResourceConstant=RESOURCE_ENERGY,amount:number=0)
    {
        if(!Game.rooms[this.roomName])
        {
            return []
        }
        return _.flatten(this._pickupPos.map(
            e=>PositionHelper.lookFor(LOOK_RESOURCES,e).filter(i=>i.amount>=amount && i.resourceType == resourceType)
            ));
    
    }

    /**
     * source周围一圈的空闲位置
     * @returns 
     */
    public getAroundPos()
    {
        return this._pickupPos
    }

    /**
     * 获取从房间储存点到source的路径
     */
    public getPath():RoomPosition[]
    {
        return this._path
    }
    /**
     * 获取完全搬运能量需要的carry数量 
     * @param CarrySpeed 在满载的情况下 移动一格需要的Tick数量  1.carry：move=1:1 速度为1 2.carry:move=2:1 2.a 有路速度为  2.b 没有路速度为2
     * @returns 
     */
    public getCarryBodyNum(CarrySpeed:number=1):number
    {
        
        // const backspeed = 1;// this.lordRoom.controller.level>=4?1:2;
        const carryamount = UtilsHelper.calCarryCapility(this.getPath().length,this.getEnergyHarvestSpeed(),CarrySpeed);
        return Math.ceil(carryamount);
    }
    
    /**
     * 挖满能量至少需要的work数量
     */
    abstract getWorkBodyNum():number;
    /**
     * 能量收入,以1500t 计算
     */
    /**
    * 获取能量采集效率 0-1
    * @returns 
    */
   protected getHarvestEfficiency(totalEnergy:number):number
   {
       // needwork 
       const work_amount = Math.ceil(totalEnergy/300/4.0*2);
       let per_position_work = 2;
       switch(this.lordRoom.controller.level)
       {
           case 1:
               per_position_work = 2;
           break;
           case 2:
               per_position_work = 3;
           break;
           default:
               per_position_work = 5;
       }
       const freecount = this.getAroundPos().length;
       // global.Log.Info(`${this.GUID()}-> ${freecount} ${per_position_work} ${work_amount}`);
       if(freecount*per_position_work>=work_amount)
       {
           return 1;
       }
      
       return freecount*per_position_work/(work_amount*1.0)
   }

    public  abstract   getEnergyHarvestSpeed():number;

    public onDestory(): boolean 
    {
        const path = this.getNodeMemory().pathkey;
        if(path)
        {
            StationNetwork.getInstance.clearPath(path);
        }
        return super.onDestory();

    }
   

    // // 缓存
    @cache_return('mine_action',0)
    public getMineActions( amount:number)
    {
        const mine = this;
        const container = mine.getContainer();
        
        if(container)
        {
            if(container.store.getUsedCapacity()>=amount)
            {
                return container;
            }
        }
        {
            const pickitem = mine.getPickUpItem();
            const max_item = _.max(pickitem,e=>e.amount);
            if(max_item && max_item.amount>=amount)
            {

                return max_item
            }
        }
        return false
    }
}
